package com.aqie.demo.Face;
import com.aqie.demo.HIKNetSDK.HCNetSDK;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
 * @author jiangxin
 * @create 2021-04-14-10:51
 * 功能：人脸库图片上传、查询、删除
 */
public class FacePicManage {
    ISAPI isapi = new ISAPI();
    //上传人脸图片
    public void uploadPic(int lUserID, String FDID) throws IOException {
        HCNetSDK.NET_DVR_FACELIB_COND struFaceLibCond = new HCNetSDK.NET_DVR_FACELIB_COND();
        struFaceLibCond.read();
        struFaceLibCond.dwSize = struFaceLibCond.size();
        struFaceLibCond.szFDID = FDID.getBytes(); //人脸库ID
        struFaceLibCond.byConcurrent = 1; //设备并发处理：0- 不开启(设备自动会建模)，1- 开始(设备不会自动进行建模)
        struFaceLibCond.byCover = 1;  //是否覆盖式导入(人脸库存储满的情况下强制覆盖导入时间最久的图片数据)：0- 否，1- 是
        struFaceLibCond.write();
        Pointer pStruFaceLibCond = struFaceLibCond.getPointer();
        int iUploadHandle = FaceMain.hCNetSDK.NET_DVR_UploadFile_V40(lUserID, HCNetSDK.IMPORT_DATA_TO_FACELIB, pStruFaceLibCond,
                struFaceLibCond.size(), null, Pointer.NULL, 0);
        if (iUploadHandle <= -1) {
            int iErr = FaceMain.hCNetSDK.NET_DVR_GetLastError();
            System.err.println("NET_DVR_UploadFile_V40失败，错误号" + iErr);
            return;
        } else {
            System.out.println("NET_DVR_UploadFile_V40成功");
        }
        HCNetSDK.NET_DVR_SEND_PARAM_IN struSendParam = new HCNetSDK.NET_DVR_SEND_PARAM_IN();
        struSendParam.read();
        //本地jpg图片转成二进制byte数组
        byte[] picbyte = toByteArray("E:\\2.Demo汇总\\JAVA_DEMO\\01-Windows_Demo\\超脑人脸比对\\Test\\pic\\FDLib.jpg");
        HCNetSDK.BYTE_ARRAY arraybyte = new HCNetSDK.BYTE_ARRAY(picbyte.length);
        arraybyte.read();
        arraybyte.byValue = picbyte;
        arraybyte.write();
        struSendParam.pSendData = arraybyte.getPointer();
        struSendParam.dwSendDataLen = picbyte.length;
        struSendParam.byPicType = 1; //图片格式：1- jpg，2- bmp，3- png，4- SWF，5- GIF
        struSendParam.sPicName = "test01".getBytes(); //图片名称
        //图片的附加信息缓冲区  图片上添加的属性信息，性别、身份等
        //1:xml文本导入方式
/*        byte[] AppendData = toByteArray("E:\\2.Demo汇总\\JAVA_DEMO\\01-Windows_Demo\\超脑人脸比对\\Test\\pic\\test.xml");
        HCNetSDK.BYTE_ARRAY byteArray = new HCNetSDK.BYTE_ARRAY(AppendData.length);
        byteArray.read();
        byteArray.byValue = AppendData;
        byteArray.write();*/
        //2:包含中文姓名的报文上传
        byte[] byFDLibName = "测试名称".getBytes("UTF-8");
        String strInBuffer1 = new String("<FaceAppendData version=\"2.0\" xmlns=\"http://www.hikvision.com/ver20/XMLSchema\"><bornTime>2014-12-12T00:00:00Z</bornTime><name>");
        String strInBuffer2 = new String("</name><sex>female</sex><province>11</province><city>01</city><certificateType>officerID</certificateType><certificateNumber>1123123123</certificateNumber><PersonInfoExtendList><PersonInfoExtend><id>1</id><enable>false</enable><name>test1</name><value>test2</value></PersonInfoExtend></PersonInfoExtendList></FaceAppendData>");
        int iStringSize = byFDLibName.length + strInBuffer1.length() + strInBuffer2.length();
        HCNetSDK.BYTE_ARRAY ptrByte = new HCNetSDK.BYTE_ARRAY(iStringSize);
        System.arraycopy(strInBuffer1.getBytes(), 0, ptrByte.byValue, 0, strInBuffer1.length());
        System.arraycopy(byFDLibName, 0, ptrByte.byValue, strInBuffer1.length(), byFDLibName.length);
        System.arraycopy(strInBuffer2.getBytes(), 0, ptrByte.byValue, strInBuffer1.length() + byFDLibName.length, strInBuffer2.length());
        ptrByte.write();
        struSendParam.pSendAppendData = ptrByte.getPointer();
        struSendParam.dwSendAppendDataLen = ptrByte.byValue.length;
        struSendParam.write();
        int iSendData = FaceMain.hCNetSDK.NET_DVR_UploadSend(lUserID, struSendParam, Pointer.NULL);
        if (iSendData <= -1) {
            int iErr = FaceMain.hCNetSDK.NET_DVR_GetLastError();
            System.err.println("NET_DVR_UploadSend失败，错误号" + iErr);
            return;
        }
        while (true) {
            IntByReference Pint = new IntByReference(0);
            int state = FaceMain.hCNetSDK.NET_DVR_GetUploadState(iSendData, Pint.getPointer());
            if (state == 1) {
                System.out.println("上传成功");
                //获取图片ID
                HCNetSDK.NET_DVR_UPLOAD_FILE_RET struUploadRet = new HCNetSDK.NET_DVR_UPLOAD_FILE_RET();
                boolean bUploadResult = FaceMain.hCNetSDK.NET_DVR_GetUploadResult(iUploadHandle, struUploadRet.getPointer(), struUploadRet.size());
                if (!bUploadResult) {
                    int iErr = FaceMain.hCNetSDK.NET_DVR_GetLastError();
                    System.err.println("NET_DVR_GetUploadResult失败，错误号" + iErr);
                } else {
                    struUploadRet.read();
                    System.out.println("图片ID：" + new String(struUploadRet.sUrl, "UTF-8"));
                }
                break;
            } else if (state == 2) {
                System.out.println("进度：" + Pint.getValue());
                continue;
            }
            System.err.println("返回值" + state);
            break;
        }
        //关闭图片上传连接
        boolean b_Close = FaceMain.hCNetSDK.NET_DVR_UploadClose(iUploadHandle);
        if (!b_Close) {
            int iErr = FaceMain.hCNetSDK.NET_DVR_GetLastError();
            System.err.println("NET_DVR_UploadSend失败，错误号" + iErr);
            return;
        }
    }
    //查询人脸比对库里的图片数据
    public void searchFaceLibData(int lUserID) {
        //POST /ISAPI/Intelligent/FDLib/FDSearch
        isapi.Isapi(lUserID, "POST /ISAPI/Intelligent/FDLib/FDSearch", XmlCreat("A5F41447CB5E41E296C92369CF1873F5", "test"));
    }
    //获取人脸比对库图片数据附加信息
    public void getFaceLibPicInfo(int lUserID, String FDID, String PID) {
        //GET /ISAPI/Intelligent/FDLib/<FDID>/picture/<PID>
        String requestUrl = "GET /ISAPI/Intelligent/FDLib/" + FDID + "/picture/" + PID;
        isapi.Isapi(lUserID, requestUrl, "");
    }
    //删除人脸比对库图片数据(包含附加信息)
    public void deleteFaceLibPicData(int lUserID, String FDID, String PID) {
        //DELETE /ISAPI/Intelligent/FDLib/<FDID>/picture/<PID>
        String requestUrl = "DELETE /ISAPI/Intelligent/FDLib/" + FDID + "/picture/" + PID;
        isapi.Isapi(lUserID, requestUrl, "");
    }
    //获取指定人脸库剩余空间（支持导入人脸图片的剩余张数）
    public void getFaceLibRemainSpace(int lUserID, String FDID) {
        // GET /ISAPI/Intelligent/FDLib/<FDID>/picture/surplusCapacity
        String requestUrl = "GET /ISAPI/Intelligent/FDLib/" + FDID + "/picture/surplusCapacity";
        System.out.println(requestUrl);
        isapi.Isapi(lUserID, requestUrl, "");
    }
    //查询的人员输入报文
    //ID:人脸库ID
    // Name： 人员姓名
    public static String XmlCreat(String ID, String Name) {
/*        <FDSearchDescription>
        <searchID>C929433A-AD10-0001-CA62-1A701E0015F2</searchID>
        <maxResults>50</maxResults>
        <searchResultPosition>0</searchResultPosition>
        <FDID>1135C03401404CC696F02B03F649ACFE</FDID>
        <name>test</name>
        <sex>male</sex>
        <province>21</province>
        <city>01</city>
        </FDSearchDescription>*/
        Document document1;
        Element root = DocumentHelper.createElement("FDSearchDescription");
        document1 = DocumentHelper.createDocument(root);
        Element searchID = root.addElement("searchID");
        searchID.setText("C929433A-AD10-0001-CA62-1A701E0015F2");
        Element maxResults = root.addElement("maxResults");
        maxResults.setText("50");
        Element searchResultPosition = root.addElement("searchResultPosition");
        searchResultPosition.setText("0");
        Element FDID = root.addElement("FDID");
        FDID.setText(ID);
        Element name = root.addElement("name");
        name.setText(Name);
        Element sex = root.addElement("sex");
        sex.setText("male");
        Element province = root.addElement("province");
        province.setText("11");
        Element city = root.addElement("city");
        city.setText("01");
        String requestXml = document1.asXML();
//        System.out.println(requestXml);
        return requestXml;
    }
    //添加人脸附加信息报文
    public static String XmlFaceAppendData() throws UnsupportedEncodingException {
/*        <FDSearchDescription>
        <searchID>C929433A-AD10-0001-CA62-1A701E0015F2</searchID>
        <maxResults>50</maxResults>
        <searchResultPosition>0</searchResultPosition>
        <FDID>1135C03401404CC696F02B03F649ACFE</FDID>
        <name>test</name>
        <sex>male</sex>
        <province>21</province>
        <city>01</city>
        </FDSearchDescription>*/
        Document document1;
        Element root = DocumentHelper.createElement("FaceAppendData");
        document1 = DocumentHelper.createDocument(root);
        Element bornTime = root.addElement("bornTime");
        bornTime.setText("2020-12-12T00:00:00Z");
        Element name = root.addElement("name");
        name.setText("test");
        Element sex = root.addElement("sex");
        sex.setText("male");
        Element province = root.addElement("province");
        province.setText("11");
        Element city = root.addElement("city");
        city.setText("01");
        Element certificateType = root.addElement("certificateType");
        certificateType.setText("officerID");
        Element certificateNumber = root.addElement("certificateNumber");
        certificateNumber.setText("1123123123");
        Element PersonInfoExtendList = root.addElement("PersonInfoExtendList");
        Element PersonInfoExtend = PersonInfoExtendList.addElement("PersonInfoExtend");
        Element id = PersonInfoExtend.addElement("id");
        id.setText("1");
        Element enable = PersonInfoExtend.addElement("enable");
        enable.setText("1");
        Element name1 = PersonInfoExtend.addElement("name");
        name1.setText("1");
        Element value = PersonInfoExtend.addElement("value");
        value.setText("1");
        String requestXml = document1.asXML();
        System.out.println(requestXml);
        return requestXml;
    }
    /**
     * 读取本地文件到数组中
     *
     * @param filename 本地文件
     * @return 返回读取到的数据到 byte数组
     * @throws IOException
     */
    public static byte[] toByteArray(String filename) throws IOException {
        File file = new File(filename);
        if (!file.exists()) {
            throw new FileNotFoundException(filename);
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
        try {
            byte[] buffer = new byte[1024];
            int len;
            while (-1 != (len = in.read(buffer, 0, buffer.length))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            bos.close();
            in.close();
        }
    }
}
